using System;
using System.Collections.Generic;
using System.ServiceModel;
using Nakio.Framework.Communication;
using Nakio.Framework.Interfaces;

namespace Nakio.Framework.Server
{
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
    public class ServerContract : Interfaces.IServerContract
    {
        private readonly ICredentialsAuthentication _credentialsAuthentication;
        private readonly Dictionary<Guid, EncryptToken> _clientsTokens;

        public ServerContract(ICredentialsAuthentication credentialsAuthentication)
        {
            _credentialsAuthentication = credentialsAuthentication;
            _clientsTokens = new Dictionary<Guid, EncryptToken>();
        }

        public EncryptToken LogClient(string username, string password)
        {
            if (_credentialsAuthentication.HasValidCredentials(username,password))
            {
                var encryptToken = new EncryptToken();
                var clientCallBack = OperationContext.Current.GetCallbackChannel<IClientCallback>(); 

                _clientsTokens.Add(clientCallBack.Guid(), encryptToken);
                return encryptToken;
            }
            return null;
        }

        public void ExecuteCommand(EncryptedCommand encryptedCommand)
        {
            var clientCallBack = OperationContext.Current.GetCallbackChannel<IClientCallback>();
            var clientToken = _clientsTokens[clientCallBack.Guid()];
            var command = encryptedCommand.DecryptCommand(clientToken, clientCallBack);
            command.Execute();
        }

        public object ExecuteReturnCommand(EncryptedCommand encryptedCommand)
        {
            var clientCallBack = OperationContext.Current.GetCallbackChannel<IClientCallback>();
            var clientToken = _clientsTokens[clientCallBack.Guid()];
            var command = encryptedCommand.DecryptCommand(clientToken, clientCallBack);
            return command.Execute();
        }

        public void LogOffClient()
        {
            var clientCallBack = OperationContext.Current.GetCallbackChannel<IClientCallback>();
            _clientsTokens.Remove(clientCallBack.Guid());
        }
    }
}